package reaction.europarl.queries.features;

import java.util.HashMap;
import java.util.Set;

import reaction.europarl.Definitions;

public class Features {
	
	public boolean correct_answer;
	
	/* textual similarities */
	public double cosine_similarity; 				 	// cosine similarity #1
	public boolean typeMatch; 						 	// 1 if candidateType and queryType are the same  #2
	public float namedEntitiesIntersection; 		 	// number of common named entities #3
	public boolean queryStringInWikiText; 			 	// 1 if the query string in candidate's text #4
	public boolean candidateNameInSupportDocument; 	 	// 1 if the candidate's string is in the support document #5
	
	/* name string similarities */
	public boolean exactMatch; 				     		// 1 if query string is equal to candidate's string #9
	public boolean querySubStringOfCandidate;     		// 1 if the query string is a substring of the candidate's string #10
	public boolean candidateSubStringOfQuery;    	 	// 1 if the candidate's string is a substring of query string #11
	public boolean queryStartsCandidateName;      		// 1 if the query string starts the candidate string #12
	public boolean queryEndsCandidateName;    	  		// 1 if the query string ends candidate string #13
	public boolean candidateNameStartsQuery;  	  		// 1 if candidate string starts query string #14 (NULL)
	public boolean candidateNameEndsQuery;    	  		// 1 if candidate string ends the query string #15 (NULL)
	public boolean queryStringAcronymOfCandidate; 		// 1 if query string is an acronym of the candidate #16
	public boolean candidateAcronymOfqueryString;	 	// 1 if candidate's string is an acronym of the query string #17 (NULL)
	
	public HashMap<String, Float> similarities = new HashMap<String, Float>();
	
	/* Hashtable containing the following keys
	 *  
	 * DiceSimilarity 		#18
	 * JaccardSimilarity	#19
	 * Jaro					#20
	 * JaroWinkler			#21
	 * Levenshtein 			#22
	 */
	public float average_similarities = 0;				// average of the 5 similarity string measures, to be used for NIL Detector
	
	/* link disambiguation */
	public int outDegree;  			// the out-degree measure according to <http://aclweb.org/anthology/I/I11/I11-1113.pdf> #23 
	public int inDegree;	  		// the in-degree measure according to <http://aclweb.org/anthology/I/I11/I11-1113.pdf>  #24	
	public double outDegreeNormalized;
	public double inDegreeNormalized;
	
	/* calculates the average of the string similarities */
	public float average_similarities() {
		Set<String> keys = similarities.keySet();
		float average = 0;
		
		for (String similarity : keys) {
			average += similarities.get(similarity);
		}
		
		return average / similarities.size();
	}

	public Features() {
		super();
	}
	
	/* returns a feature vector */
	public double[] featuresVector(){
		
		double[] inputVector = new double[24];
		
		if (Definitions.textualSimilarities) {
			
			// cosine
			inputVector[0] = this.cosine_similarity;
			
			// query is in the wiki text
			if (this.queryStringInWikiText) {
				inputVector[2] = 1;
			}
			
			// candidate name string is in the support document
			if (this.candidateNameInSupportDocument) {
				inputVector[3] = 1;
			}
		}
		
		if (Definitions.nameSimilarities) {
			
			if (this.exactMatch) {
				inputVector[8] = 1;
			}
			
			if (this.querySubStringOfCandidate) {
				inputVector[9] = 1;
			}
			
			if (this.candidateSubStringOfQuery) {
				inputVector[10] = 1;
			}
			
			if (this.queryStartsCandidateName) {
				inputVector[11] = 1;
			}
			
			if (this.queryEndsCandidateName) {
				inputVector[12] = 1;
			}
			
			if (this.candidateNameStartsQuery) {
				inputVector[13] = 1;
			}
			
			if (this.candidateNameEndsQuery) {
				inputVector[14] = 1;
			}
			
			if (this.queryStringAcronymOfCandidate) {
				inputVector[15] = 1;
			}
			
			if (this.candidateAcronymOfqueryString) {
				inputVector[16] = 1;
			}
			
			inputVector[17] = (double) similarities.get("DiceSimilarity");
			inputVector[18] = (double) similarities.get("JaccardSimilarity");
			inputVector[19] = (double) similarities.get("Jaro");
			inputVector[20] = (double) similarities.get("JaroWinkler");
			inputVector[21] = (double) similarities.get("Levenshtein");
			
		}
		
		/*
		if (Definitions.linkDisambiguation) {
			inputVector[22] = this.inDegree;
			inputVector[23] = this.outDegree;			
		}
		*/
		
		return inputVector;
	}

}